local snow = require("meet_your_mods.mhr").snow

local input = {
    pad_code = {
        snow.Pad.Button.LT, snow.Pad.Button.RT, snow.Pad.Button.LB, snow.Pad.Button.RB,
        snow.Pad.Button.LS, snow.Pad.Button.RS,
        snow.Pad.Button.CL, snow.Pad.Button.CR, snow.Pad.Button.CC,
        snow.Pad.Button.LU, snow.Pad.Button.LD, snow.Pad.Button.LL, snow.Pad.Button.LR,
        snow.Pad.Button.RU, snow.Pad.Button.RD, snow.Pad.Button.RL, snow.Pad.Button.RR,
    },
    pad_mask  = snow.Pad.Button.Decide - 1,
    pad_label = {
        [0] = {
           [snow.Pad.Button.LU]  = "U",      [snow.Pad.Button.LD]= "D",     [snow.Pad.Button.LL]= "L",    [snow.Pad.Button.LR]= "R",
           [snow.Pad.Button.RU]  = "Y",      [snow.Pad.Button.RD]= "A",     [snow.Pad.Button.RL]= "X",    [snow.Pad.Button.RR]= "B",
           [snow.Pad.Button.LT]  = "LB",     [snow.Pad.Button.LB]= "LT",    [snow.Pad.Button.RT]= "RT",   [snow.Pad.Button.RB]= "RB",
           [snow.Pad.Button.LS]  = "LS",     [snow.Pad.Button.RS]= "RS",
           [snow.Pad.Button.CL]  = "View",   [snow.Pad.Button.CR]= "Menu",  [snow.Pad.Button.CC]= "XboX",
        },
        [1] = {
           [snow.Pad.Button.LU]  = "U",        [snow.Pad.Button.LD]= "D",     [snow.Pad.Button.LL]= "L",      [snow.Pad.Button.LR]= "R",
           [snow.Pad.Button.RU]  = "Triangle", [snow.Pad.Button.RD]= "Cross", [snow.Pad.Button.RL]= "Square", [snow.Pad.Button.RR]= "Circle",
           [snow.Pad.Button.LT]  = "L1",       [snow.Pad.Button.LB]= "L2",    [snow.Pad.Button.RT]= "R1",     [snow.Pad.Button.RB]= "R2",
           [snow.Pad.Button.LS]  = "L3",       [snow.Pad.Button.RS]= "R3",
           [snow.Pad.Button.CL]  = "Select",   [snow.Pad.Button.CR]= "Start", [snow.Pad.Button.CC]= "PS",
        },
        [2] = {
           [snow.Pad.Button.LU]  = "U",      [snow.Pad.Button.LD]= "D",     [snow.Pad.Button.LL]= "L",    [snow.Pad.Button.LR]= "R",
           [snow.Pad.Button.RU]  = "X",      [snow.Pad.Button.RD]= "B",     [snow.Pad.Button.RL]= "Y",    [snow.Pad.Button.RR]= "A",
           [snow.Pad.Button.LT]  = "L",      [snow.Pad.Button.LB]= "ZL",    [snow.Pad.Button.RT]= "R",    [snow.Pad.Button.RB]= "ZR",
           [snow.Pad.Button.LS]  = "LS",     [snow.Pad.Button.RS]= "RS",
           [snow.Pad.Button.CL]  = "－",     [snow.Pad.Button.CR]= "＋",     [snow.Pad.Button.CC]= "Home",
        },
    },
    key_label = {
        [1] = "LButton",
        [2] = "RButton",
        [3] = "Cancel",
        [4] = "MButton",
        [5] = "XButton1",
        [6] = "XButton2",
        [8] = "Back",
        [9] = "Tab",
        [12] = "Clear",
        [13] = "Enter",
        [16] = "Shift",
        [17] = "Control",
        [18] = "Menu",
        [19] = "Pause",
        [20] = "Capital",
        [21] = "Kana",
        [23] = "Junja",
        [24] = "Final",
        [25] = "Hanja",
        [27] = "Escape",
        [28] = "Convert",
        [29] = "NonConvert",
        [30] = "Accept",
        [31] = "ModeChange",
        [32] = "Space",
        [33] = "Prior",
        [34] = "Next",
        [35] = "End",
        [36] = "Home",
        [37] = "Left",
        [38] = "Up",
        [39] = "Right",
        [40] = "Down",
        [41] = "Select",
        [42] = "Print",
        [43] = "Execute",
        [44] = "SnapShot",
        [45] = "Insert",
        [46] = "Delete",
        [47] = "Help",
        [48] = "0",
        [49] = "1",
        [50] = "2",
        [51] = "3",
        [52] = "4",
        [53] = "5",
        [54] = "6",
        [55] = "7",
        [56] = "8",
        [57] = "9",
        [65] = "A",
        [66] = "B",
        [67] = "C",
        [68] = "D",
        [69] = "E",
        [70] = "F",
        [71] = "G",
        [72] = "H",
        [73] = "I",
        [74] = "J",
        [75] = "K",
        [76] = "L",
        [77] = "M",
        [78] = "N",
        [79] = "O",
        [80] = "P",
        [81] = "Q",
        [82] = "R",
        [83] = "S",
        [84] = "T",
        [85] = "U",
        [86] = "V",
        [87] = "W",
        [88] = "X",
        [89] = "Y",
        [90] = "Z",
        [91] = "LWin",
        [92] = "RWin",
        [93] = "Apps",
        [95] = "Sleep",
        [96] = "NumPad0",
        [97] = "NumPad1",
        [98] = "NumPad2",
        [99] = "NumPad3",
        [100] = "NumPad4",
        [101] = "NumPad5",
        [102] = "NumPad6",
        [103] = "NumPad7",
        [104] = "NumPad8",
        [105] = "NumPad9",
        [106] = "Multiply",
        [107] = "Add",
        [108] = "Separator",
        [109] = "Subtract",
        [110] = "Decimal",
        [111] = "Divide",
        [112] = "F1",
        [113] = "F2",
        [114] = "F3",
        [115] = "F4",
        [116] = "F5",
        [117] = "F6",
        [118] = "F7",
        [119] = "F8",
        [120] = "F9",
        [121] = "F10",
        [122] = "F11",
        [123] = "F12",
        [124] = "F13",
        [125] = "F14",
        [126] = "F15",
        [127] = "F16",
        [128] = "F17",
        [129] = "F18",
        [130] = "F19",
        [131] = "F20",
        [132] = "F21",
        [133] = "F22",
        [134] = "F23",
        [135] = "F24",
        [144] = "NumLock",
        [145] = "Scroll",
        [146] = "NumPadEnter",
        [160] = "LShift",
        [161] = "RShift",
        [162] = "LControl",
        [163] = "RControl",
        [164] = "LMenu",
        [165] = "RMenu",
        [186] = "OEM_1",
        [187] = "OEM_Plus",
        [188] = "OEM_Comma",
        [189] = "OEM_Minus",
        [190] = "OEM_Period",
        [192] = "OEM_3",
        [219] = "OEM_4",
        [221] = "OEM_6",
        [222] = "OEM_7",
        [223] = "OEM_8",
        [226] = "OEM_102",
        [191] = "Slash",
        [220] = "BackSlash",
        [254] = "DefinedEnter",
        [255] = "DefinedCancel",
    },
    option = nil,
    pad    = nil,
    key    = nil,
}

function input:get_pad_label(command)
    if command < snow.Pad.Button.LU or command > snow.Pad.Button.CC then
        return nil
    end

    local pad_label = self.pad_label[self:pad_icon_type()>>1]
    local label     = ""
    for _, code in pairs(self.pad_code) do
        if code == (command & code) then
            label = label .. "+" .. pad_label[code]
        end
    end

    return string.sub(label, 2)
end

function input:fetch_option()
    if self.option then
        return self.option
    end

    local option_manager = snow.StmOptionManager:get_singleton()
    if option_manager then
        self.option = option_manager:get_StmOptionDataContainer()
    end
    return self.option
end

function input:pad_icon_type()
    return input:fetch_option()
            and self.option:getPadButtonIconOption()
            or  snow.StmOptionDef.PadButtonIconOption.ns
end

function input:fetch_pad()
    if self.pad then
        return self.pad
    end

    local pad = snow.Pad:get_singleton()
    if pad then
        self.pad = pad.hard
    end
    return self.pad
end

function input:pad_getOn()
    return input:fetch_pad()
            and self.pad:get_on() & self.pad_mask
            or  snow.Pad.Button.None
end

function input:pad_andOn(command)
    return input:fetch_pad()
            and self.pad:andOn(command & self.pad_mask)
            or  false
end

function input:fetch_key()
    if self.key then
        return self.key
    end

    local keyboard = snow.GameKeyboard:get_singleton()
    if keyboard then
        self.key = keyboard.hardKeyboard
    end
    return self.key
end

function input:get_key_label(command)
    if command <= 0 then
        return nil
    end
    return self.key_label[command]
end

function input:key_getTrg(command)
    return self:fetch_key()
            and self.key:getTrg(command)
            or  false
end

function input:key_getDown()
    if not self:fetch_key() then
        return 0
    end

    for key, _ in pairs(self.key_label) do
        if self.key:getDown(key) then
            return key
        end
    end
    return 0
end

function input:ui_andTrg(command)
    return snow.gui.StmGuiInput:andTrg(command, 0, 0, 0, 0, 0, 0, 0, 0, 0, false, false)
end

function input:initialize()
end

snow.StmOptionDef.PadButtonIconOption:fetch_enum("xbox_1", "Type1")
snow.StmOptionDef.PadButtonIconOption:fetch_enum("xbox_2", "Type2")
snow.StmOptionDef.PadButtonIconOption:fetch_enum("ps_1", "Type3")
snow.StmOptionDef.PadButtonIconOption:fetch_enum("ps_2", "Type4")
snow.StmOptionDef.PadButtonIconOption:fetch_enum("ns", "Type5")

return input